package ACoForest;

/**
 * @author david
 *
 */

import java.io.*;
import java.util.Random;

import weka.core.*;
import weka.classifiers.trees.*;
import weka.classifiers.bayes.*;
import weka.classifiers.functions.Logistic;

public class Exp 
{

	public static void main(String[] args){
		PrepareData pda = new PrepareData();
		pda.getBugs();
		
		pda.run("Functionality");
		run();
		
		pda.run("Usability");
		run();
		
		pda.run("Security");
		run();
		
		pda.run("Performance");
		run();
	}
	
	/**
	 * @param args
	 */
	public static void run() 
	{
//		final int NUM_RUNS = 100;
		final int NUM_RUNS = 1;
		String fp = "output/ACoForest/";
		
		 int seed = 0;
	     int numFeatures = 0;
	     Random rand = new Random(seed);
	     final int NUM_CLASSIFIERS = 10;
		
		double[] vPrecision = new double[NUM_RUNS];
		double[] vRecall = new double[NUM_RUNS];
		double[] vF1 = new double[NUM_RUNS];
		
		double[] vPrecision_J48 = new double[NUM_RUNS];
		double[] vRecall_J48 = new double[NUM_RUNS];
		double[] vF1_J48 = new double[NUM_RUNS];
		
		double[] vPrecision_NB = new double[NUM_RUNS];
		double[] vRecall_NB = new double[NUM_RUNS];
		double[] vF1_NB = new double[NUM_RUNS];
		
		double[] vPrecision_Log = new double[NUM_RUNS];
		double[] vRecall_Log = new double[NUM_RUNS];
		double[] vF1_Log = new double[NUM_RUNS];
		

		try
		{
		int iRun = 0;
//	  	  for(int iRun = 0; iRun < NUM_RUNS; iRun++)
		  {
	  		 System.out.println("iRun = " + iRun);
			 BufferedReader r = new BufferedReader(new FileReader(fp + "train" +  ".arff"));
		     Instances labeled = new Instances(r);
		     labeled.setClassIndex(0);
		     r.close();
		     
		     r = new BufferedReader(new FileReader(fp+"test" + ".arff"));
		     Instances unlabeled = new Instances(r);
		     unlabeled.setClassIndex(0);
		     r.close();
		     //splitLabeled(labeled, unlabeled, rand);
		     
		     Instances test = unlabeled;
		     int numBefore= unlabeled.numInstances();
		     
		     ACoForest aforest = new ACoForest();
		     aforest.setNumSelectedInst(20);
		     aforest.setNumClassifiers(NUM_CLASSIFIERS);
		     aforest.setNumFeatures(numFeatures);
		     aforest.setSeed(rand.nextInt());
		     aforest.buildClassifier(labeled, unlabeled);
		     int numAfter = unlabeled.numInstances();
		     System.out.println("numSelected = " + (numBefore-numAfter)+"\n");
		     
		     double[] vPredictions = new double[test.numInstances()];
		     double[] vTrueValues = new double[test.numInstances()];
		     
		     for(int i = 0; i < test.numInstances(); i++)
		     {
		    	 vPredictions[i] = aforest.classifyInstance(test.instance(i));
		    	 vTrueValues[i] = test.instance(i).classValue();
		     }
		     measureF1(vPredictions, vTrueValues, vPrecision, vRecall, vF1, iRun);
		     
		     r = new BufferedReader(new FileReader(fp + "train" + ".arff"));
		     labeled = new Instances(r);
		     labeled.setClassIndex(0);
		     r.close();
		     
		     r = new BufferedReader(new FileReader(fp+"test" +  ".arff"));
		     unlabeled = new Instances(r);
		     unlabeled.setClassIndex(0);
		     r.close();
		     
		     //splitLabeled(labeled, unlabeled, rand);
		     

		     test = unlabeled;		    
		     
		     Logistic logestic = new Logistic();
		     logestic.buildClassifier(labeled);
		     
		     J48 j48 = new J48();
		     j48.buildClassifier(labeled);
		     
		     NaiveBayes nb = new NaiveBayes();
		     nb.buildClassifier(labeled);
		     
		     
		     vTrueValues = new double[test.numInstances()];
		     double[] vPredictions_J48 = new double[test.numInstances()];
		     double[] vPredictions_NB = new double[test.numInstances()];
		     double[] vPredictions_Log = new double[test.numInstances()];
		     for(int i = 0; i < test.numInstances(); i++)
		     {
		    	 Instance inst = test.instance(i);
		    	 vPredictions_J48[i] = j48.classifyInstance(inst);
		    	 vPredictions_NB[i] = nb.classifyInstance(inst);
		    	 vPredictions_Log[i] = logestic.classifyInstance(inst);
		    	 vTrueValues[i] = inst.classValue();
		     }
		     measureF1(vPredictions_J48, vTrueValues, vPrecision_J48, vRecall_J48, vF1_J48, iRun);
		     measureF1(vPredictions_NB, vTrueValues, vPrecision_NB, vRecall_NB, vF1_NB, iRun);
		     measureF1(vPredictions_Log, vTrueValues, vPrecision_Log, vRecall_Log, vF1_Log, iRun);
		     
		     
		  } //end of for
	  	  
	  	  double avgPre = Utils.sum(vPrecision)/NUM_RUNS;
	  	  double avgRec = Utils.sum(vRecall) / NUM_RUNS;
	  	  double avgF1 = Utils.sum(vF1) /NUM_RUNS;
	  	  	  
	  	  double avgPre_J48 = Utils.sum(vPrecision_J48)/NUM_RUNS;
	  	  double avgRec_J48 = Utils.sum(vRecall_J48) / NUM_RUNS;
	  	  double avgF1_J48 = Utils.sum(vF1_J48) /NUM_RUNS;
	  	  
	  	  double avgPre_NB = Utils.sum(vPrecision_NB)/NUM_RUNS;
	  	  double avgRec_NB = Utils.sum(vRecall_NB) / NUM_RUNS;
	  	  double avgF1_NB = Utils.sum(vF1_NB) /NUM_RUNS;
	  	  
	      double avgPre_Log = Utils.sum(vPrecision_Log)/NUM_RUNS;
	  	  double avgRec_Log = Utils.sum(vRecall_Log) / NUM_RUNS;
	  	  double avgF1_Log = Utils.sum(vF1_Log) /NUM_RUNS;
	  	  
	  	  System.out.println("AvgPre = " + avgPre);
	  	  System.out.println("AvgRec = " + avgRec);
	  	  System.out.println("AvgF1 = " + avgF1);
	  	   	  
	      System.out.println("\nAvgPre_J48 = " + avgPre_J48);
	  	  System.out.println("AvgRec_J48 = " + avgRec_J48);
	  	  System.out.println("AvgF1_J48 = " + avgF1_J48);
	  	  
	  	  System.out.println("\nAvgPre_NB = " + avgPre_NB);
	  	  System.out.println("AvgRec_NB = " + avgRec_NB);
	  	  System.out.println("AvgF1_NB = " + avgF1_NB);
	  	  
	  	  System.out.println("\nAvgPre_Log = " + avgPre_Log);
	  	  System.out.println("AvgRec_Log = " + avgRec_Log);
	  	  System.out.println("AvgF1_Log = " + avgF1_Log);
	  	  
	  	  System.out.println("-------------------------------------------------");
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		

	}
	
	static void measureF1(double[] vPredictions, double[] vTrueValue, double[] vP, double[] vR, double[] vF, int iRun) throws Exception
	{
		double tp = 0;
		double fp = 0;
		double fn = 0;
		double tn = 0;
		
		for(int i = 0; i < vPredictions.length; i++)
		{
			if(vPredictions[i] == 0 && vTrueValue[i] == 0)
				tp +=1;
			else if(vPredictions[i] == 0 && vTrueValue[i] == 1)
				fp +=1;
			else if(vPredictions[i] == 1 && vTrueValue[i] == 0)
				fn +=1;
			else if(vPredictions[i] == 1 && vTrueValue[i] == 1)
				tn +=1;
			else
				throw new Exception("Some Exceptions");

		}
		
		vP[iRun] = tp / (tp+fp);
		vR[iRun] = tp / (tp + fn);
		vF[iRun] = 2*vP[iRun]*vR[iRun] / (vP[iRun] + vR[iRun]);
	}
	
	static void splitLabeled(Instances labeled, Instances unlabeled, Random rand)
	{
		labeled.randomize(rand);
		int numToKeep = labeled.numInstances()/2;
		int numOriginal = labeled.numInstances();
		for(int i = numToKeep; i < numOriginal; i++)
		{
			unlabeled.add(labeled.instance(numToKeep));
			labeled.delete(numToKeep);
		}
		
		
	}
	

}
